"Les cours de neeko.fr"

Retour en haut

Utilisation des ListView dans Android

Utilisation de ListView dans Android

Afficher des listes de vues.

Principe d'une ListView

ListView est une vue à intégrer comme n'importe quelle autre vue dans un layout.

Elle est très pratique pour afficher une série d'éléments identiques (ou avec des variantes) dans un scroll.

Elle permet aussi d'optimiser la mémoire en "recyclant" les vues de chaque "cellule".

A noter qu'une grande partie de ce qui s'applique aux ListView s'applique aussi aux GridView.

Utiliser une ListView : un Adapter et un Listener

Pour configurer et utiliser une ListView, on utilise la plupart du temps 2 interfaces :
ListAdapter et OnItemClickListener

L'indispensable ListAdapter

Le principe est qu'une ListView à besoin d'un objet qui va l'informer de ce qu'elle doit afficher.

Cet objet doit implémenter l'interface ListAdapter. C'est cet objet qui va par exemple décider du nombre d'éléments à afficher dans la liste, et à créer les vues pour chaque cellules.

A noter que cet adapter peut être utilisé par d'autres classes, en particulier par GridView.

Pour définir un adapter pour notre liste, il suffit d'avoir un objet qui implémente l'interface ListAdapter, et de le passer à notre liste :

maSuperListe.setAdapter(monSuperAdapter);

Les méthodes de l'interface

L'interface défini 12 méthodes ! On peut les regrouper en 3 parties :

Concernant la liste complète
int getCount()

Cette méthode doit renvoyer le nombre d'élément total contenu par la liste.

boolean isEmpty()

Cette méthode doit indiquer si la liste est complètement vide ou pas.

int getViewTypeCount()

Cette méthode doit indiquer le nombre d'élements de type différent dans la liste.

Les éléments sont considérés de types différents s'ils ne vont pas utilliser la même vue. Si tous les éléments de la liste auront le même type, il suffit d'écrire return 1

boolean areAllItemsEnabled()

Cette méthode détermine si tous les éléments sont clickables, ou si certains ne le sont pas.

Si vous répondez "false", alors la méthode isEnabled() sera appellée pour chaque éléments.

boolean hasStableIds()

Inutile pour nous, on repondra systématiquement true.

Concernant un élément de la liste

Ces méthodes seront appellées automatiquement pour chacun de nos éléments.

Elles recevront alors en paramètre int position, qui corespond à la position dans la liste. .

View getView(int position, View convertView, ViewGroup parent)

Cette méthode doit renvoyer la vue pour l'élément. Ici on peut soit construire une vue "à la main", soit utiliser un layout XML.

Voir le chapitre plus loin pour cette méthode.

boolean isEnabled(int position)

Permet de déterminer si l'élément est actif ou non. Elle ne sera appellée que si areAllItemsEnabled a répondu false.

int getItemViewType(int position)

Cette méthode doit renvoyer le type de l'élément. Le type est simplement un int, et est utilisé par Android pour le recyclage des vues. Voir le chapitre plus loin pour le recyclage de vues.

Si on a qu'un seul type d'élements (comme défini par getViewTypeCount), il suffit de renvoyer toujours la même valeur. Par exemple return 1.

Object getItem(int position)

Cette méthode doit renvoyer l'objet correspondant à l'élément. Que ce soit un String, ou un objet User, ou quoi que ce soit, il faut le revoyer ici.

Dans certains cas seulement cette méthode est utilisée, par exemple pour gérer les selections dans la liste.

long getItemId(int position)

Cette méthode permet de définir un identifiant unique l'élément. La plupart du temps, il suffit de donner la position de l'élément en guise d'identifiant.

Cet identifiant sera passé au listener au moment du click sur l'élément.

Concernant les utilisateurs de notre adapter
void registerDataSetObserver(DataSetObserver observer)

La plupart du temps, c'est la ListView qui interroge l'adapter pour savoir comment se comporter.

Il est parfois utile que l'adapter prévienne la ListView que quelque chose à changé dans les données.

C'ests la ListView s'inscrit auprès de l'adapter : l'observer reçu ici en parametre correspond à la ListView, mais "cachée derriere" une interface : DataSetObserver.

On pourra alors choisir prévenir cet observateur en cas de changement dans nos données en appellant des méthodes de DataSetObserver (onChanged(), par exemple).

void unregisterDataSetObserver(DataSetObserver observer)

La liste se désinscrit et ne souhaite plus recevoir de notification.

En résumé

Une fois la liste et l'adapter connectés (grace à la méthode list.setAdapter()) voici le déroulement typique :

Etapeméthode appelléeExemple de valeur renvoyée par l'adapteur
Est ce que tous les élements de la liste sont actifs ? areAllItemsEnabled() true
Combien y-a-t'il d'éléments dans la liste ? getCount() 15
Enregistre la liste en tant qu'observateur en cas de changement dans les données registerDataObserver(instanceDeMaListe) void
Combien de types de vues différents ? getViewTypeCount() 1
...
Quelle vue pour le premier élément ? getView(0, null, maListe) une View
Quel est le type du premier élément ? getItemViewType(0) 1
Quelle vue pour le second élément ? getView(1, null, maListe) une View
Quel est le type du second élément ? getItemViewType(1) 1
...
Quelle vue pour le 15e élément ? getView(14, laVueDeLElement1, maListe) laVueDeLElement1, modifiée
Quel est le type du second élément ? getItemViewType(14) 1
Dans le détail : getView()

Cette méthode est appellée pour chaque élément de la liste.

View getView(int position, View convertView, ViewGroup parent)

L'implémention la plus simple serait de construire une nouvelle vue à chaque fois :

TextView maCellule = new TextView(...); maCellule.setText("Cellule numéro " + position); return maCellule;

C'est tout à fait possible, mais pas recommandé. On préfère en général utilise le system service "LayoutInflater" pour lire un layout XML.

Attention, pour utiliser le LayoutInflater, on a besoin d'un Context...

LayoutInflater inflater = (LayoutInflater) monContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View maCellule = inflater.inflate(R.layout.list_cell, parent, false); return maCellule;

Recyclage

Enfin, il est possible de recycler certaines vues. C'est Android qui décide de nous permettre de recycler une vue.

C'est le rôle du parametre convertView. Il peut être NULL, ce qui signifie que l'on doit construire une nouvelle vue. S'il n'est pas NULL, on peut modifier cette vue pour l'élement demandé.

Voici une implémentation complete :

public View getView(int position, View convertView, ViewGroup parent) { View cellView = convertView; if (cellView == null) { LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); cellView = inflater.inflate(R.layout.list_cell, parent, false); } TextView titleView = (TextView) cellView.findViewById(R.id.title); TextView contentView = (TextView) cellView.findViewById(R.id.content); titleView.setText("Ma cellule"); contentView.setText("position : " + position); return cellView; }

Le OnItemClickListener

Ce listener s'utilise très simplement pour savoir quel élément à été cliqué dans la liste. C'est le même principe que un onClickListener sur un boutton, mais la liste nous passe un peu plus d'informations.

Pour s'inscrire :

maSuperListe.setOnItemClickListener(monSuperListener);

L'interface OnItemClickListener nous oblige à implémenter la méthode :

public void onItemClick (AdapterView parent, View view, int position, long id)

Description des paramètres :

TP : Liste de villes

Vous allez créer un simple projet qui affichera la liste des plus grandes ville du monde dans un ListView.

Les "données" seront simplement stockées dans un ArrayList, et l'adapter manipulera ce tableau pour fournir les informations à la ListView.

Projet

L'adapter

Initialisation

Implémenataion

Aller plus loin